package com.szeldon.declatest.runners;

import java.util.logging.Logger;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;

import com.szeldon.utils.ValuesUtils;

/**
 * Used for interpreting command line arguments as parameters for Declatest.
 * 
 * @author szeldon
 * 
 */
public class CLIInterpreter {

    private static final String TEST_SUITE_DECLARATION_FILENAME_OPTION = "s";
    private static final String XML_REPORT_DATA_DIRECTORY_OPTION = "d";
    private static final String REPORT_PLUGINS_DIRECTORY_OPTION = "p";

    private static Logger logger = Logger.getLogger(CLIInterpreter.class.getName());

    private String[] args;

    //
    private String testSuiteDeclarationFilename;
    private String xmlReportDataDirectory;
    private String reportPluginsDirectory;

    /**
     * Creates interpreter for given command line arguments. Remember that before getting interpreted data,
     * {@link #interpretArgs()} method has to be called.
     * 
     * @param args
     */
    public CLIInterpreter(String[] args) {
        this.args = args;
    }

    /**
     * Interprets arguments. After calling this method, interpreted data may be get using other methods.
     * 
     * @throws ParseException
     */
    public void interpretArgs() throws ParseException {

        Options options = createOptions();

        CommandLineParser parser = new PosixParser();
        CommandLine cmd = parser.parse(options, args);

        interpretParsedOptions(cmd, options);
    }

    private void interpretParsedOptions(CommandLine cmd, Options options) throws ParseException {
        testSuiteDeclarationFilename = cmd.getOptionValue(TEST_SUITE_DECLARATION_FILENAME_OPTION);
        xmlReportDataDirectory = cmd.getOptionValue(XML_REPORT_DATA_DIRECTORY_OPTION);
        reportPluginsDirectory = cmd.getOptionValue(REPORT_PLUGINS_DIRECTORY_OPTION);

        try {
            ValuesUtils.checkNamedValueForNull("testSuiteDeclarationFilename", testSuiteDeclarationFilename);
            ValuesUtils.checkNamedValueForNull("xmlReportDataFilePath", xmlReportDataDirectory);
            ValuesUtils.checkNamedValueForNull("reportPluginsDirectory", reportPluginsDirectory);
        } catch (IllegalArgumentException e) {
            logger.severe("Bad command line arguments. " + e.getMessage());
            HelpFormatter formatter = new HelpFormatter();
            formatter.printHelp("See options below:", options);
            throw new ParseException("Bad command line arguments. " + e.getMessage());
        }
    }

    private Options createOptions() {
        Options options = new Options();

        options.addOption(TEST_SUITE_DECLARATION_FILENAME_OPTION, true,
                "Path for file containing test suite declaration to be used.");
        options.addOption(XML_REPORT_DATA_DIRECTORY_OPTION, true,
                "Directory that will contain report data files after test suite execution.");
        options.addOption(REPORT_PLUGINS_DIRECTORY_OPTION, true, "Directory that will contain reports.");

        return options;
    }

    /**
     * Returns name of file that was passed in command line arguments as one with declaration of test suite.
     * 
     * @return
     */
    public String getTestSuiteDeclarationFilename() {
        return testSuiteDeclarationFilename;
    }

    /**
     * Returns a name of directory that was passed in command line arguments as one that should contain report data.
     * 
     * @return
     */
    public String getXmlReportDataDirectory() {
        return xmlReportDataDirectory;
    }

    /**
     * Returns a name of directory that was passed in command line arguments as one that should contain reports
     * generated by plugins for different formats of reports.
     * 
     * @return
     */
    public String getReportPluginsDirectory() {
        return reportPluginsDirectory;
    }

}
